﻿using FirstFloor.ModernUI.Presentation;
using SelElectCalcModernUI.Lib;
using SelElectCalcModernUI.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SelElectCalcModernUI.ViewModel.CalcRes
{
    public class FactoryResultViewModel
        : NotifyPropertyChanged, IDisposable
    {
        FactoryResModel factoryResData;
        CommandBase returnCmd;
        CommandBase exportCmd;
        ObservableCollection<string> factoryResFilters;
        string factoryResFilter;
        ObservableCollection<FactoryResSignle> factoryResFiltersRes;
        ObservableCollection<FactoryResSignle> factoryResFiltersResDetail;
        ObservableCollection<Model.KeyValuePair<string, double>> totInfo;
        public FactoryResModel FactoryResData
        {
            get
            {
                if (factoryResData == null)
                    factoryResData = new FactoryResModel();
                return factoryResData;
            }
        }
        public CommandBase ReturnCmd
        {
            get
            {
                if (returnCmd == null)
                    returnCmd = new RelayCommand((s) =>
                    {
                        ViewModelLocator.JumpPageEvent("/Pages/HomePage.xaml");
                    });
                return returnCmd;
            }
        }

        public CommandBase ExportCmd
        {
            get
            {
                if (exportCmd == null)
                    exportCmd = new RelayCommand((s) =>
                    {
                        SaveFile();
                    }, (s) => FactoryResData.FactoryRes != null && FactoryResData.FactoryRes.Count > 0);
                return exportCmd;
            }
        }

        public ObservableCollection<string> FactoryResFilters
        {
            get
            {
                if (factoryResFilters == null)
                    factoryResFilters = new ObservableCollection<string>();
                factoryResFilters.Clear();
                var filters = from c in FactoryResData.FactoryRes group c.Factory by c.Factory into g select g;
                factoryResFilters.Add("全部");
                foreach (var filter in filters)
                    factoryResFilters.Add(filter.Key);
                return factoryResFilters;
            }
        }

        public string FactoryResFilter
        {
            get
            {
                if (string.IsNullOrWhiteSpace(factoryResFilter))
                    factoryResFilter = "全部";
                return factoryResFilter;
            }

            set
            {
                factoryResFilter = value;
                OnPropertyChanged("FactoryResFilter");
                OnPropertyChanged("FactoryResFiltersRes");
                OnPropertyChanged("FactoryResFiltersResDetail");
            }
        }

        public ObservableCollection<FactoryResSignle> FactoryResFiltersRes
        {
            get
            {
                if (factoryResFiltersRes == null)
                    factoryResFiltersRes = new ObservableCollection<FactoryResSignle>();
                factoryResFiltersRes.Clear();
                var res = from c in FactoryResData.FactoryRes where c.Factory.Equals(factoryResFilter) select c;
                if (factoryResFilter != "全部")
                    foreach (var item in res)
                        factoryResFiltersRes.Add(item);
                else
                    foreach (var item in FactoryResData.FactoryRes)
                        factoryResFiltersRes.Add(item);
                AddTotAndAvgRow(factoryResFiltersRes);
                CalcTotInfo();
                FactoryResData.TotPower =
                    factoryResFiltersRes.Sum((ss) => ss.RealPower);
                FactoryResData.TotPrice =
                    factoryResFiltersRes.Sum((ss) => ss.RealPrice * ss.RealPower);
                FactoryResData.EveryPrice =
                    FactoryResData.TotPrice / FactoryResData.TotPower;
                FactoryResData.TotReturnPrice =
                    factoryResFiltersRes.Sum((ss) => (ss.RealPrice - ss.OrgPrice) * ss.RealPower);
                return factoryResFiltersRes;
            }
        }

        public ObservableCollection<FactoryResSignle> FactoryResFiltersResDetail
        {
            get
            {
                if (factoryResFiltersResDetail == null)
                    factoryResFiltersResDetail = new ObservableCollection<FactoryResSignle>();
                factoryResFiltersResDetail.Clear();
                var res = from c in FactoryResData.FactoryResDetail where c.Factory.Equals(factoryResFilter) select c;
                if (factoryResFilter != "全部")
                    foreach (var item in res)
                        factoryResFiltersResDetail.Add(item);
                else
                    foreach (var item in FactoryResData.FactoryResDetail)
                        factoryResFiltersResDetail.Add(item);
                AddTotAndAvgRow(factoryResFiltersResDetail);
                return factoryResFiltersResDetail;
            }
        }

        private void CalcTotInfo()
        {
            //throw new NotImplementedException();
            TotInfo[0].Value = FactoryResData.FactoryRes.Sum(s=>s.TotNoBackPrice) - ViewModelLocator.SellerResult.SellerResData.SellerRes.Sum(s => s.TotNoBackPrice);
            TotInfo[1].Value = TotInfo[0].Value * ViewModelLocator.OtherSetting.FactoryBackRage / 100;
            TotInfo[2].Value = FactoryResData.FactoryRes.Sum(s => s.TotNoBackPrice) - FactoryResData.FactoryRes.Sum(s => s.TotBackPrice);
            TotInfo[3].Value = FactoryResData.FactoryRes.Sum(s => s.OrgPower * s.OrgPrice) / FactoryResData.FactoryRes.Sum(s => s.OrgPower) * 1000;
            TotInfo[4].Value = FactoryResData.FactoryRes.Min(s=>s.OrgPrice) * 1000;
            TotInfo[5].Value = FactoryResData.FactoryRes.Max(s => s.OrgPrice) * 1000;
            TotInfo[6].Value = FactoryResData.FactoryRes.Sum(s => s.OrgPrice * s.RealPower) / FactoryResData.FactoryRes.Sum(s=>s.RealPower) * 1000;
            TotInfo[7].Value = FactoryResData.FactoryRes.Min(s => s.RealPrice) * 1000;
            TotInfo[8].Value = FactoryResData.FactoryRes.Max(s => s.RealPrice) * 1000;
            TotInfo[9].Value = FactoryResData.FactoryRes.Sum(s => s.RealPrice * s.RealPower) / FactoryResData.FactoryRes.Sum(s => s.RealPower) * 1000;
            foreach (var item in totInfo)
            {
                item.Value = Math.Round(item.Value,2);
            }
        }

        public ObservableCollection<Model.KeyValuePair<string, double>> TotInfo
        {
            get
            {
                if (totInfo == null)
                { 
                    totInfo = Model.KeyValuePair<string, double>.CreatList("供需中标电量申报价差电费总额（万元）",
"返还给供方（万元）",
"供应侧累计让利（万元）",
"供应侧总平均申报价差（厘 / kWh）",
"供应侧中标售电量最终成交最低申报价差（厘 / kWh）",
"供应侧中标售电量最终成交最高申报价差（厘 / kWh）",
"供应侧中标售电量最终成交平均申报价差（厘 / kWh）",
"供应侧中标售电量最终成交最低结算价差（厘 / kWh）",
"供应侧中标售电量最终成交最高结算价差（厘 / kWh）",
"供应侧中标售电量最终成交平均结算价差（厘 / kWh）");
                }
                return totInfo;
            }
        }

        private void AddTotAndAvgRow(IList<FactoryResSignle> factories)
        {
            FactoryResSignle totRow = new FactoryResSignle()
            {
                Seller = string.Empty,
                Factory = "累计值",
                DealTotPerSeat = -1,
                InSeat = -1,
                Times = -1,
                OrgPrice = double.NaN,
                AvgOrgPrice = double.NaN,
                RealPrice = double.NaN,
                AvgBackPrice = double.NaN,
                PerIn = double.NaN,
                DealPer = factories.Sum(s => s.RealPower) / factories.Sum(s => s.OrgPower),
                DealTotPer = factories.Sum(s => s.DealTotPer),
                OrgPower = factories.Sum(s => s.OrgPower),
                RealPower = factories.Sum(s => s.RealPower),
                SurplusPower = factories.Sum(s => s.SurplusPower),
                TotBackPrice = factories.Sum(s => s.TotBackPrice),
                TotDifPrice = factories.Sum(s => s.TotDifPrice),
                TotIn = factories.Sum(s => s.TotIn),
                TotNoBackPrice = factories.Sum(s => s.TotNoBackPrice),
                TotPrice = factories.Sum(s => s.TotPrice),
                TotPriceRange = factories.Sum(s => s.TotPriceRange)
            };
            FactoryResSignle avgRow = new FactoryResSignle()
            {
                Seller = string.Empty,
                Factory = "平均值",
                DealTotPerSeat = -1,
                InSeat = -1,
                Times = -1,
                OrgPrice = factories.Sum(s => s.OrgPower * s.OrgPrice) / totRow.OrgPower,
                AvgOrgPrice = factories.Sum(s => s.RealPower * s.OrgPrice) / totRow.RealPower,
                RealPrice = (totRow.TotBackPrice - totRow.TotNoBackPrice) / totRow.RealPower,
                AvgBackPrice = totRow.TotBackPrice / totRow.RealPower,
                PerIn = double.NaN,
                DealPer = double.NaN,
                DealTotPer = double.NaN,
                OrgPower = double.NaN,
                RealPower = double.NaN,
                SurplusPower = double.NaN,
                TotBackPrice = double.NaN,
                TotDifPrice = double.NaN,
                TotIn = double.NaN,
                TotNoBackPrice = double.NaN,
                TotPrice = double.NaN,
                TotPriceRange = double.NaN
            };
            factories.Add(totRow);
            factories.Add(avgRow);
        }

        private void SaveFile()
        {
            var stream = ViewModelLocator.SaveFileEvent("csv");
            if (stream == null)
                return;
            System.IO.StreamWriter tr = new System.IO.StreamWriter(stream, Encoding.Default);
            SaveFileString(tr);
            tr.Flush();
            tr.Close();
        }

        public void SaveFileString(System.IO.StreamWriter tr)
        {
            tr.WriteLine("供应方统计");
            tr.WriteLine("供应侧,(总)申报电量(万kWh),(平均)申报价差(厘/kWh),(总)中标售电量(万kWh)," +
                "(平均)中标售电量申报价差(厘/kWh),(总)中标售电量申报价差电费(万元),(总)中标售电量返还需方价差电费(万元)," +
                "(平均)中标售电量返还需方价差(厘/kWh),(平均)中标售电量最终成交结算价差(厘/kWh),(平均)中标售电量单位收益(厘/kWh)," +
                "(平均)中标售电量单位收益排名,(总)中标售电量本次总收益(万元),(总)各方中标售电量占各方申报售电量比例(%)," +
                "(总)各方中标售电量占总允许成交电量比例(%),(总)各方中标售电量占总允许成交电量比例 排名,(总)各方剩余电量(万Kwh)," +
                "(总)各方中标售电量占总成交电费比例(%),(总)各方中标电费(万元),(总)各方差价电费(万元)");
            List<FactoryResSignle> temp = (from c in FactoryResData.FactoryRes select c).ToList();
            AddTotAndAvgRow(temp);
            foreach (var se in temp)
            {
                tr.WriteLine(se.Factory + "," + se.OrgPower.GetString() + "," + (se.OrgPrice * 1000).GetString() + "," + se.RealPower.GetString() + "," + (se.AvgOrgPrice * 1000).GetString()
                    + "," + se.TotNoBackPrice.GetString() + "," + se.TotBackPrice.GetString() + "," + (se.AvgBackPrice * 1000).GetString() + "," + (se.RealPrice * 1000).GetString()
                    + "," + (se.PerIn * 1000).GetString() + "," + se.InSeat.GetString() + "," + se.TotIn.GetString() + "," + (se.DealPer * 100).GetString() + "," + (se.DealTotPer * 100).GetString()
                    + "," + se.DealTotPerSeat.GetString() + "," + se.SurplusPower.GetString() + "," + (se.TotPriceRange * 100).GetString() + "," + se.TotPrice.GetString() + ","
                    + se.TotDifPrice.GetString());
            }
            tr.WriteLine("供应方价次统计");
            tr.WriteLine("供应侧,报价次数,(总)申报电量(万kWh),(平均)申报价差(厘/kWh),(总)中标售电量(万kWh)," +
                "(平均)中标售电量申报价差(厘/kWh),(总)中标售电量申报价差电费(万元),(总)中标售电量返还需方价差电费(万元)," +
                "(平均)中标售电量返还需方价差(厘/kWh),(平均)中标售电量最终成交结算价差(厘/kWh),(平均)中标售电量单位收益(厘/kWh)," +
                "(平均)中标售电量单位收益排名,(总)中标售电量本次总收益(万元),(总)各方中标售电量占各方申报售电量比例(%)," +
                "(总)各方中标售电量占总允许成交电量比例(%),(总)各方中标售电量占总允许成交电量比例 排名,(总)各方剩余电量(万Kwh)," +
                "(总)各方中标售电量占总成交电费比例(%),(总)各方中标电费(万元),(总)各方差价电费(万元)");
            temp = (from c in FactoryResData.FactoryResDetail select c).ToList();
            AddTotAndAvgRow(temp);
            foreach (var se in temp)
            {
                tr.WriteLine(se.Factory + "," + se.Times.GetString() + "," + se.OrgPower.GetString() + "," + (se.OrgPrice * 1000).GetString() + "," + se.RealPower.GetString() + "," + (se.AvgOrgPrice * 1000).GetString()
                    + "," + se.TotNoBackPrice.GetString() + "," + se.TotBackPrice.GetString() + "," + (se.AvgBackPrice * 1000).GetString() + "," + (se.RealPrice * 1000).GetString()
                    + "," + (se.PerIn * 1000).GetString() + "," + se.InSeat.GetString() + "," + se.TotIn.GetString() + "," + (se.DealPer * 100).GetString() + "," + (se.DealTotPer * 100).GetString()
                    + "," + se.DealTotPerSeat.GetString() + "," + se.SurplusPower.GetString() + "," + (se.TotPriceRange * 100).GetString() + "," + se.TotPrice.GetString() + ","
                    + se.TotDifPrice.GetString());
            }
            CalcTotInfo();
            foreach (var info in totInfo)
            {
                tr.WriteLine(info.Key + "," + info.Value);
            }
        }

        public void Dispose()
        {
        }
    }
}
